#ifndef KEY_H
#define KEY_H

#include "system_config.h"
#include "device.h"
#include "event.h"

#define KEY_SHORT_TIME 30
#define KEY_LONG_TIME 800
#define KEY_SUPERLONG_TIME 1800

#define KEY_SCAN_CHANGE(key, interval, evt) \
	{                                       \
		static unsigned char key_prev_state = 0;     \
		static unsigned int c = 0;          \
                                            \
		if (c == 0)                         \
		{                                   \
			key_prev_state = key;           \
			c++;                            \
		}                                   \
		else                                \
		{                                   \
			if (key != key_prev_state)      \
			{                               \
				c++;                        \
				if (c > interval)           \
				{                           \
					event_post(evt);        \
					key_prev_state = key;   \
					c = 1;                  \
				}                           \
			}                               \
			else                            \
			{                               \
				c = 1;                      \
			}                               \
		}                                   \
	}
	

//suitable for a single press(either short press or long press)
#define KEY_SCAN_RELEASE(key, interval, release_event) \
	{                                                                     \
		static unsigned int c = 0;                                        \
                                                                          \
		if (key == 0)                                                     \
		{                                                                 \
			c++;                                                          \
			if (c == (interval))                                          \
			{                                                             \
				event_post(press_event);                                  \
			}                                                             \
			else if (c > (interval))                                      \
			{                                                             \
				c = (interval);                                           \
			}                                                             \
		}                                                                 \
		else                                                              \
		{                                                                 \
			if (c >= (interval))                                          \
			{                                                             \
				event_post(release_event);                                \
			}                                                             \
			c = 0;                                                        \
		}                                                                 \
	}

//suitable for a single press(either short press or long press)
#define KEY_SCAN_PRESS_RELEASE(key, interval, press_event, release_event) \
	{                                                                     \
		static unsigned int c = 0;                                        \
                                                                          \
		if (key == 0)                                                     \
		{                                                                 \
			c++;                                                          \
			if (c == (interval))                                          \
			{                                                             \
				event_post(press_event);                                  \
			}                                                             \
			else if (c > (interval))                                      \
			{                                                             \
				c = (interval);                                           \
			}                                                             \
		}                                                                 \
		else                                                              \
		{                                                                 \
			if (c >= (interval))                                          \
			{                                                             \
				event_post(release_event);                                \
			}                                                             \
			c = 0;                                                        \
		}                                                                 \
	}

//suitable for a single press(either short press or long press)
#define KEY_SCAN_DOWN_PRESS_RELEASE(key, interval, down_event, press_event, release_event) \
	{                                                                                      \
		static unsigned int c = 0;                                                         \
                                                                                           \
		if (key == 0)                                                                      \
		{                                                                                  \
			c++;                                                                           \
			if (c == 1)                                                                    \
			{                                                                              \
				event_post(down_event);                                                    \
			}                                                                              \
			if (c == (interval))                                                           \
			{                                                                              \
				event_post(press_event);                                                   \
			}                                                                              \
			else if (c > (interval))                                                       \
			{                                                                              \
				c = (interval);                                                            \
			}                                                                              \
		}                                                                                  \
		else                                                                               \
		{                                                                                  \
			if (c >= (interval))                                                           \
			{                                                                              \
				event_post(release_event);                                                 \
			}                                                                              \
			c = 0;                                                                         \
		}                                                                                  \
	}

//suitable for both short press and long press withou release event
#define KEY_SCAN_SHORT_LONG(key, short_interval, short_event, long_interval, long_event) \
	{                                                                                    \
		static unsigned int c = 0;                                                       \
                                                                                         \
		if (key == 0)                                                                    \
		{                                                                                \
			c++;                                                                         \
			if (c == (long_interval))                                                    \
			{                                                                            \
				event_post(long_event);                                                  \
			}                                                                            \
			else if (c > (long_interval))                                                \
			{                                                                            \
				c = (long_interval);                                                     \
			}                                                                            \
		}                                                                                \
		else                                                                             \
		{                                                                                \
			if ((c >= (short_interval)) && (c < (long_interval)))                        \
			{                                                                            \
				event_post(short_event);                                                 \
			}                                                                            \
			c = 0;                                                                       \
		}                                                                                \
	}

//suitable for both short press and long press with release event
#define KEY_SCAN_SHORT_LONG_RELEASE(key, short_interval, short_event, short_release_event, long_interval, long_event, long_release_event) \
	{                                                                                                                                     \
		static unsigned int c = 0;                                                                                                        \
                                                                                                                                          \
		if (key == 0)                                                                                                                     \
		{                                                                                                                                 \
			c++;                                                                                                                          \
			if (c == (short_interval))                                                                                                    \
			{                                                                                                                             \
				event_post(short_event);                                                                                                  \
			}                                                                                                                             \
			else if (c == (long_interval))                                                                                                \
			{                                                                                                                             \
				event_post(long_event);                                                                                                   \
			}                                                                                                                             \
			else if (c > (long_interval))                                                                                                 \
			{                                                                                                                             \
				c = (long_interval);                                                                                                      \
			}                                                                                                                             \
		}                                                                                                                                 \
		else                                                                                                                              \
		{                                                                                                                                 \
			if ((c >= (short_interval)) && (c < (long_interval)))                                                                         \
			{                                                                                                                             \
				event_post(short_release_event);                                                                                          \
			}                                                                                                                             \
			else if((c >= (long_interval))																						\
			{																																					\
				event_poset(long_release_event);																				\
			}																																					\
			c = 0;                                                                                                                        \
		}                                                                                                                                 \
	}

//suitable for short/long/superlong press with release event
#define KEY_SCAN_SHORT_LONG_SUPERLONG_RELEASE(key, short_interval, short_event, short_release_event, long_interval, long_event, long_release_event, superlong_interval, superlong_event, superlong_release_event) \
	{                                                                                                                                                                                                             \
		static unsigned int c = 0;                                                                                                                                                                                \
                                                                                                                                                                                                                  \
		if (key == 0)                                                                                                                                                                                             \
		{                                                                                                                                                                                                         \
			c++;                                                                                                                                                                                                  \
			if (c == (short_interval))                                                                                                                                                                            \
			{                                                                                                                                                                                                     \
				event_post(short_event);                                                                                                                                                                          \
			}                                                                                                                                                                                                     \
			else if (c == (long_interval))                                                                                                                                                                        \
			{                                                                                                                                                                                                     \
				event_post(long_event);                                                                                                                                                                           \
			}                                                                                                                                                                                                     \
			else if (c == (superlong_interval))                                                                                                                                                                   \
			{                                                                                                                                                                                                     \
				event_post(superlong_event);                                                                                                                                                                      \
			}                                                                                                                                                                                                     \
			else if (c > (superlong_interval))                                                                                                                                                                    \
			{                                                                                                                                                                                                     \
				c = (superlong_interval);                                                                                                                                                                         \
			}                                                                                                                                                                                                     \
		}                                                                                                                                                                                                         \
		else                                                                                                                                                                                                      \
		{                                                                                                                                                                                                         \
			if ((c >= (short_interval)) && (c < (long_interval)))                                                                                                                                                 \
			{                                                                                                                                                                                                     \
				event_post(short_release_event);                                                                                                                                                                  \
			}                                                                                                                                                                                                     \
			else if ((c >= (long_interval)) && (c < (superlong_interval)))                                                                                                                                        \
			{                                                                                                                                                                                                     \
				event_post(long_release_event);                                                                                                                                                                   \
			}                                                                                                                                                                                                     \
			else if((c >= (superlong_interval))																				\
			{																																					\
				event_poset(superlong_release_event);																		\
			}																																					\
			c = 0;                                                                                                                                                                                                \
		}                                                                                                                                                                                                         \
	}

//for backward compactibility
#define KEY_ROUTINE(key, short_interval, short_event, long_interval, long_event) KEY_SCAN_SHORT_LONG(key, short_interval, short_event, long_interval, long_event)

#endif